package mips.instructions;

/**
 * <code>SLTIU</code> instruction<br/>
 * Set On Less Than Immediate Unsigned<br/>
 * @author jnmartin84@gmail.com
 */
public class SLTIU extends Instruction {

	private static final SLTIU INSTANCE = new SLTIU();
	private static final String INSTRUCTION_NAME = "SLTIU";

	private SLTIU(){}

	public static final SLTIU getInstance() {
		return INSTANCE;
	}

	/**
	 * <b>Format:</b><br/>
	 * SLTIU rt, rs, immediate<br/><br/>
	 * <b>Description:</b><br/>
	 * The 16-bit immediate is sign-extended and subtracted from the contents of<br/>
	 * general register rs. Considering both quantities as unsigned integers, if rs<br/>
	 * is less than the sign-extended immediate, the result is set to one; otherwise<br/>
	 * the result is set to zero.<br/><br/>
	 * The result is placed into general register rt.<br/><br/>
	 * No integer overflow exception occurs under any circumstances. The<br/>
	 * comparison is valid even if the subtraction used during the comparison<br/>
	 * overflows.<br/><br/>
	 * <b>Operation:</b><br/>
	 * T: if (0 || GPR[rs]) < (immediate<sub>15</sub>)<sup>16</sup> || immediate<sub>15...0</sub> then<br/>
	 * GPR[rt] &larr; 0<sup>31</sup> || 1<br/>
	 * else<br/>
	 * GPR[rt] &larr; 0<sup>32</sup><br/>
	 * endif 
	 */
	@Override
	public final void execute(final int instruction) {
		
		final int rs = (instruction >> 21) & 0x0000001F;
		final int rt = (instruction >> 16) & 0x0000001F;
		final int immed = Instruction.signExtendH((instruction) & 0x0000FFFF);
		
		final long _rs = (long) (mips.R4300i.GPR[rs] & 0x00000000FFFFFFFFL);
		final long _immed = (long) (immed & 0x00000000FFFFFFFFL);
		
		if(_rs < _immed) {
			mips.R4300i.GPR[rt] = 1;
		}
		else {
			mips.R4300i.GPR[rt] = 0;			
		}
		
		mips.R4300i.PC = mips.R4300i.nPC;
		mips.R4300i.nPC = mips.R4300i.PC + 4;
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final String emit(final int instruction) {

		final int rs = (instruction >> 21) & 0x0000001F;
		final int rt = (instruction >> 16) & 0x0000001F;
		final int immed = Instruction.signExtendH((instruction) & 0x0000FFFF);
		
		return	"		u32_gpr_rs = (long) (mips.CPU.GPR["+rs+"] & 0x00000000FFFFFFFFL);\n" + 
				"		u32_immed = (long) ("+immed+" & 0x00000000FFFFFFFFL);\n" + 
				"		\n" + 
				"		if(_rs < _immed) {\n" + 
				"			mips.CPU.GPR["+rt+"] = 1;\n" + 
				"		}\n" + 
				"		else {\n" + 
				"			mips.CPU.GPR["+rt+"] = 0;\n" + 
				"		}\n" + 
				"		\n" + 
				"		mips.CPU.PC = mips.CPU.nPC;\n" + 
				"		mips.CPU.nPC = mips.CPU.PC + 4;\n";
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final String getName(final int instruction) {
		return getName();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public final String getName() {
		return INSTRUCTION_NAME;
	}
}